home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d26
/
asmtut4.arc
/
CHAP20.DOC
< prev
next >
Wrap
Text File
|
1990-08-10
|
13KB
|
447 lines
212
CHAPTER 20 - CONTROL STRUCTURES
Control structures are things like 'for', 'do', 'while' and 'if'
that you have in high level languages. It is possible to do these
things in assembler language if you want. They are included here
so if you ever want to use them at this level, you will have a
template on how to set them up.
All the examples will use integers only. If you have real
numbers:
if ( variable < 3.891 )
x = 4 * y ;
it is too difficult to implement on the 8086. Of course, if you
have an 8087, it's a piece of cake.
IF
IF is the easiest and it will illustrate how we are going to set
up our labels. Let's take that first example. Since it is a waste
of space to define variables over and over, we will assume that
all variables are words, not bytes. The examples will all be
written in C.
if (variable < 7)
{
x = 4 + y ;
}
The assembler code looks like this:
if1: ;----------------
cmp variable, 7
jge end_if1
mov x, 4
mov ax, y
add x, ax
end_if1: ;----------------
All labels will look like variations of this. The control words
will be the labels.{1} They will have a unique number for each
block so you can write as many different blocks as you want; the
label that signals the end of the block will be the word 'end_'
followed by the control word. The semicolon with the line is a
____________________
1. The words 'if' and 'endif' are Microsoft macro directives,
so if you use them without a tag number, you will get some
bizarre code indeed.
______________________
The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
Chapter 20 - Control Structures 213
_______________________________
comment, and it is used for visual separation.
By using a different number each time, you may nest as deeply as
you want, though the code will be pretty unreadable:
if (variable < 7 )
{
if ( x > 9 )
{
if ( z == 0 )
{
y = 12 ;
}
q = 5 ;
}
r = 7 ;
}
becomes:
if1: ;---------------
cmp variable, 7
jge end_if1
if2: ;---------------
cmp x, 9
jle end_if2
if3: ;---------------
cmp z, 0
jne end_if3
mov y, 12
end_if3: ;-----------
mov q, 5
end_if2: ;-----------
mov r, 7
end_if1: ;-----------
With the Microsoft assembler, you don't need to have the labels
start at the beginning of the line, but they MUST be the first
thing on the line. You can indent them:
if1: ; --------------
cmp variable, 7
jge end_if1
if2: ;-------------
cmp x, 9
jle end_if2
if3: ;------------
cmp z, 0
jne end_if3
mov y, 12
The PC Assembler Tutor 214
______________________
end_if3: ;--------
mov q, 5
end_if2: ;---------
mov r, 7
end_if1: ;---------
You will notice that they are all compares and jumps using
reverse logic. If the condition is NOT true, then we jump. If it
is true, we just go on. What about IF ELSE? It looks almost the
same.
if ( j < 12 )
{
y = 19 ;
}
else
{
z = 25 ;
}
We get:
if16: ;----------------
cmp j, 12
jge else16
mov y, 19
jmp end_if16
else16:
mov z, 25
end_else16:
end_if16: ;---------------
We jump to another part inside the block, and throw in a JMP
after the IF part.
WHILE
WHILE is the same as IF except that at the end of the block, we
jump back to the beginning.
while ( j < 20 )
{
j = j + 1 ;
}
while25: ;------------
cmp j, 20
jge end_while25
inc j
jmp while25
end_while25: ;-----------
Chapter 20 - Control Structures 215
_______________________________
DO WHILE
DO WHILE always goes through the code once. The decision process
is at the end.
do
{
k = k + 7 ;
} while (k < 0) ;
do_while74: ;------------
add k, 7
cmp k, 0
jl do_while74
end_do_while74: ;------------
Notice that here the jump is a positive decision. If the
condition is fulfilled, we jump back to the start, otherwise we
fall through. What do you do with 'break' and 'continue'? {2}
Let's put them in:
do
{
k = k + 7 ;
if ( y < 9 )
{
continue ;
}
j = j - 6 ;
if ( z == 5 )
{
break ;
}
y = y * 2 ;
} while ( j < 17) ;
In assembler language, this becomes:
do_while143: ;----------
add k, 7
if144: ;-----------
cmp y, 9
jge end_if144
jmp continue143
end_if144: ;-----------
sub j, 6
____________________
2. For those of you who are not C people, BREAK breaks you out
of the innermost loop. CONTINUE skips all the code till the end
of the loop.
The PC Assembler Tutor 216
______________________
if145: ;-----------
cmp z, 5
jne end_if145
jmp break143
end_if145: ;-----------
sal y, 1 ; shift left 1 = multiply by 2
continue143:
cmp j, 17
jl do_while143
end_do_while143:
break143:
In DO WHILE, CONTINUE is the label just before the decision
process. BREAK is always the first label after the block. We can
just use the label that marks the end of our block for the break.
Instead of:
jmp break143
we can have:
jmp end_do_while143
From now on, we'll put in the continue and break, even if they
aren't used. Once you are used to it, you can drop the break
label and use the end of block label. Going back to the WHILE
statement, we have:
while25: ;------------
cmp j, 20
jge end_while25
inc j
continue25:
jmp while25
end_while25: ;-----------
break25:
FOR
The FOR statement in C is more sophisticated than in other
languages, but we will keep the example simple. It has 3 parts:
for ( i = 11 ; i < 20 ; i = i + 1 )
can be looked at as:
for ( initialize ; test ; update )
The reason that it is sophisticated is that it can have any
number of things in the first and third parts.
Chapter 20 - Control Structures 217
_______________________________
for ( i = 11, j = 27 z = 4 ; i < 20 ; k = k + 1, j = j/2)
is legitimate. Therefore we need to set aside a block for the
initialize part, a block for the test part, and a block for the
update part. One question is whether we want the initialization
inside the FOR label. I'm not doing it, but it is a possibility.
Here's the C code.
for ( i = 11 ; i < 20 ; i = i + 1 )
{
k = k + 9
}
And its corresponding assembler code:
init217: ;---------------
mov i, 11
end_init217: ;------
for217: ; ---------------
test217:
cmp i, 20
jge end_for217
end_test217: ;-----
add k,9
continue217:
update217:
inc i
end_update217: ; ----
jmp test217
end_for217: ;-------------
break217:
My that's a lot of labels. In this example we would get rid of
most of them because there is so little code, but if the block
contained a lot of code they would be a help, not a hindrance.
Remember, a label generates no code, so this makes no difference
in the size of the object file. Some of the labels which are not
targets of jumps could be made into comments.
end_update217: ;----
can become:
; end_update217 ----
Whichever way looks better to you. Using comments instead of
labels gives you a slightly faster compile time. Just make sure
you don't change one that IS a target of a jump.
SWITCH
Finally there is the switch statement. If you don't know what it
is, skip this section because it will probably be confusing.
The PC Assembler Tutor 218
______________________
switch ( k )
{
case 'A': x = x + 9 ;
break ;
case '&': y = y * 2 ;
break ;
case 'j': z = z - 7 ;
break ;
}
We get the following:
switch82: ;-----------------
cmp k, 'A'
jne test82_2
jmp case82_1
test82_2
cmp k, '&'
jne test82_3
jmp case82_2
test82_3
cmp k, 'j'
jne end_test82
jmp case82_3
end_test82:
jmp deafult82
; ----------
case82_1:
add x, 9
jmp break82
case82_2:
sal y, 1 ; multiply by 2
jmp break82
case82_3:
sub z, 7
jmp break82
default82:
jmp break82
end_switch82: ;------------
break82:
It may look like there are unnecessary jumps at the beginning,
but it is likely that in a real program some of the case
statements would be more than +127 bytes away from the
conditional jumps, so you need JMP, which can go anywhere in the
segment.